package xcmg.device.service.warehouse;

import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import xcmg.device.dao.entity.barcode.BarcodeManageDO;
import xcmg.device.dao.entity.split.SplitDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesPurDO;
import xcmg.device.dao.entity.warehouse.AbnormalInDO;
import xcmg.device.dao.entity.warehouse.AbnormalInDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.mapper.BarcodeManageMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.split.SplitMapper;
import xcmg.device.dao.mapper.warehouse.*;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.enums.AbnormalInAuditStatusEnum;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.infra.exception.CommonBusiExceptions;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.basic.SystemParameterService;
import xcmg.device.service.delivery.DeliveryReceiptMaterialService;
import xcmg.device.service.packageSpec.PackageSpecService;
import xcmg.device.service.threeGuaranteesPur.ThreeGuaranteesPurService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.basic.MaterialsSearchVO;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.vo.warehouse.AbnormalInAddVO;
import xcmg.device.service.vo.warehouse.AbnormalInDetailVO;
import xcmg.device.service.vo.warehouse.AbnormalInVO;
import xcmg.device.service.vo.warehouse.BillTypeConfigVO;
import xcmg.device.service.vo.warehouse.sap.ObligateVO;
import xcmg.device.util.DecimalUtil;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AbnormalInService {
    @Resource
    private AbnormalInMapper abnormalInMapper;
    @Resource
    private AbnormalInDetailMapper abnormalInDetailMapper;
    @Resource
    private AbnormalInDetailService abnormalInDetailService;
    @Resource
    private GenDocumentService genDocumentService;
    @Resource
    private FastGenClient fastGenClient;
    @Resource
    private HttpServletResponse response;
    @Resource
    private BillTypeConfigService billTypeConfigService;
    @Resource
    private WarehouseInboundService warehouseInboundService;
    @Resource
    private CommonService commonService;
    @Resource
    private MaterialsService materialsService;
    @Resource
    private WarehouseInboundDetailMapper warehouseInboundDetailMapper;
    @Resource
    private PriMaterialsMapper priMaterialsMapper;
    @Resource
    private SystemParameterService systemParameterService;
    @Resource
    private SplitMapper splitMapper;
    @Resource
    private DeliveryReceiptMaterialService deliveryReceiptMaterialService;
    @Resource
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;
    @Resource
    private BarcodeManageMapper barcodeManageMapper;
    @Resource
    private WarehouseDOMapper warehouseDOMapper;
    @Value("${spring.file.download.path}")
    private String filePath;
    private String templateExcelFileName = "UnNormalInImport.xls";

    /**
     * 出库状态：手动完成
     */
    private static final Integer OUT_STATUS_FINISH = 3;
    /**
     * 过账状态。2已过账
     */
    private static final Integer POST_STATUS_YES = 2;
    @Resource
    private ThreeGuaranteesPurService threeGuaranteesPurService;
    @Resource
    private PackageSpecService packageSpecService;


    /**
     * @Description: 生成非正常入库单记录
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode add(AbnormalInAddVO abnormalInAddVO, String userId, String orgId, boolean isExternalInterfaceCall) throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }
        AbnormalInVO abnormalInVO = abnormalInAddVO.getHeaderInfo();
        AbnormalInDO abnormalInDO = new AbnormalInDO();
        BeanUtils.copyProperties(abnormalInVO, abnormalInDO);

        //判断拆件单号是否存在
        if (!StringUtil.isNullOrEmpty(abnormalInVO.getSplitOrder())) {
            SplitDO splitDO = splitMapper.selectBySplitOrder(abnormalInVO.getSplitOrder(), orgId);
            if (splitDO == null) {
                return ErrorCode.splitNotExist;
            }
        }

        abnormalInDO.setId(textResult.getValue());
        abnormalInDO.setAbnormalNo(genDocumentService.genDocumentNo(BillDesc.AbnoramlIn, orgId));


        abnormalInDO.setState(0);
        abnormalInDO.setApplicationDate(new Date());
        abnormalInDO.setOrgId(orgId);

        abnormalInDO.setCreateId(userId);
        abnormalInDO.setCreateName(isExternalInterfaceCall ? abnormalInVO.getUserName() : commonService.getUserName(userId));

        BillTypeConfigVO config = billTypeConfigService.findByPK(abnormalInVO.getTypeId());
        if (config != null) {
            abnormalInDO.setIsSynsap(config.getIsSynsap());
            abnormalInDO.setType(config.getType());
            abnormalInDO.setMoveType(config.getMoveType());
        } else {
            abnormalInDO.setIsSynsap(0);
        }
        //设置单据保存时的审核状态
        saveAbnormalInInitAudit(abnormalInDO);
        boolean success = abnormalInMapper.insert(abnormalInDO) > 0;

        if (success) {
            //新增非正常入库详情记录
            List<ObligateVO> obligateVOList = new ArrayList<>();
            ObligateVO obligateVO;
            List<AbnormalInDetailVO> detailVOList = abnormalInAddVO.getDetailList();
            if (CollectionUtils.isNotEmpty(detailVOList)) {
                for (AbnormalInDetailVO detail : detailVOList) {
                    detail.setAbnormalNo(abnormalInDO.getAbnormalNo());
                    detail.setCreateId(userId);
                    detail.setOrgId(orgId);
                    success = abnormalInDetailService.add(detail).getCode() == 0;
                    if (!success) {
                        throw new Exception("新增非正常入库详情记录失败");
                    }

                    //根据crmOrder回写三包申请实际返厂状态
                    if (!StringUtil.isNullOrEmpty(detail.getCrmOrder())) {
                        ThreeGuaranteesPurDO threeGuaranteesPurDO = new ThreeGuaranteesPurDO();
                        threeGuaranteesPurDO.setCrmOrder(detail.getCrmOrder());
                        threeGuaranteesPurDO.setActualReturn("1");
                        threeGuaranteesPurService.updateByCrmOrder(threeGuaranteesPurDO);
                    }

                    //判断是否需要同步到sap创建预留单
                    if (abnormalInDO.getIsSynsap() == 1) {
                        obligateVO = new ObligateVO();
                        obligateVO.setMaterialNo(detail.getMaterialsNo());
                        obligateVO.setAmount(detail.getQty());
                        obligateVO.setSapInArea(abnormalInVO.getSapInArea());
                        obligateVO.setInnerOrder(abnormalInDO.getInnerOrder());
                        obligateVO.setMoveType(abnormalInDO.getMoveType());
                        obligateVO.setWarehouseCode(abnormalInDO.getInLocation());
                        obligateVOList.add(obligateVO);
                    }

                    //如果是由发运交接单生成，更新发运交接单状态
                    if (!StringUtil.isNullOrEmpty(abnormalInVO.getReceiptId())) {
                        deliveryReceiptMaterialService.updateSendStatus(abnormalInVO.getReceiptId(), abnormalInVO.getReceiptNo(), detail.getMaterialsNo(), detail.getQty());
                    }
                }
            }

            //生成入库主记录和入库详情记录
            abnormalInVO.setAbnormalNo(abnormalInDO.getAbnormalNo());
            abnormalInAddVO.setHeaderInfo(abnormalInVO);
            success = warehouseInboundService.saveByAbnormalIn(abnormalInAddVO, userId, orgId, abnormalInVO.getSupplierOrgId());
            if (!success) {
                throw new Exception("生成入库主记录和入库详情记录出错");
            }

        }
        ErrorCode code = success ? ErrorCode.Success : ErrorCode.Failure;
        return code;
    }

    /**
     * @Des 保存其他入库单时设置单据的初始审核状态
     * @Date 2021/4/14 19:43
     * @Author wangzhaoyu
     * @Param [abnormalInDO]
     * @Return void
     */
    private void saveAbnormalInInitAudit(AbnormalInDO abnormal) {

        if (abnormal == null) {
            return;
        }
        boolean abnormalInAuditSetting = systemParameterService.getAbnormalInAuditSetting(abnormal.getOrgId());
        if (abnormalInAuditSetting) {//需要走审核流程
            abnormal.setAuditStatus(AbnormalInAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
        } else {//不需要走审核流程
            abnormal.setAuditStatus(AbnormalInAuditStatusEnum.AUDIT_PASS.getAuditStatus());
            abnormal.setAuditDate(new Date());
            abnormal.setAuditRemark(null);
            abnormal.setAuditUserId("0001");
            abnormal.setAuditUserName("系统自动");
        }
    }


//    @Transactional(rollbackFor = Exception.class)
//    public ActionResult add4CRM(AbnormalInAddVO abnormalInAddVO, String userId, String orgId, boolean isExternalInterfaceCall) throws Exception {
//        ActionResult<String> textResult = fastGenClient.textGuid();
//        if (textResult.getCode() != ErrorCode.Success.getCode()) {
//            throw new Exception("生成GUID出错");
//        }
//        AbnormalInVO abnormalInVO = abnormalInAddVO.getHeaderInfo();
//        AbnormalInDO abnormalInDO = new AbnormalInDO();
//        BeanUtils.copyProperties(abnormalInVO, abnormalInDO);
//
//        abnormalInDO.setId(textResult.getValue());
//        abnormalInDO.setAbnormalNo(genDocumentService.genDocumentNo(BillDesc.AbnoramlIn, orgId));
//        abnormalInDO.setState(0);
//        abnormalInDO.setApplicationDate(new Date());
//        abnormalInDO.setOrgId(orgId);
//
//        abnormalInDO.setCreateId(userId);
//        abnormalInDO.setCreateName(isExternalInterfaceCall ? abnormalInVO.getUserName() : commonService.getUserName(userId));
//
//        BillTypeConfigVO config = billTypeConfigService.findByPK(abnormalInVO.getTypeId());
//        if (config != null) {
//            abnormalInDO.setIsSynsap(config.getIsSynsap());
//            abnormalInDO.setType(config.getType());
//            abnormalInDO.setMoveType(config.getMoveType());
//        } else {
//            abnormalInDO.setIsSynsap(0);
//        }
//        boolean success = abnormalInMapper.insert(abnormalInDO) > 0;
//
//        if (success) {
//            //新增非正常入库详情记录
//            List<ObligateVO> obligateVOList = new ArrayList<>();
//            ObligateVO obligateVO;
//            List<AbnormalInDetailVO> detailVOList = abnormalInAddVO.getDetailList();
//            if (CollectionUtils.isNotEmpty(detailVOList)) {
//                for (AbnormalInDetailVO detail : detailVOList) {
//                    if (StringUtils.isBlank(detail.getMaterialsDes())) {
//                        PriMaterialsDO materialsDO = priMaterialsMapper.itemByNo(detail.getMaterialsNo(), orgId);
//                        if (null != materialsDO) {
//                            detail.setMaterialsDes(materialsDO.getMaterialsDes());
//                        }
//                    }
//                    detail.setAbnormalNo(abnormalInDO.getAbnormalNo());
//                    detail.setCreateId(userId);
//                    detail.setOrgId(orgId);
//                    success = abnormalInDetailService.add(detail).getCode() == 0;
//                    if (!success) {
//                        throw new Exception("新增非正常入库详情记录失败");
//                    }
//
//                    //判断是否需要同步到sap创建预留单
//                    if (abnormalInDO.getIsSynsap() == 1) {
//                        obligateVO = new ObligateVO();
//                        obligateVO.setMaterialNo(detail.getMaterialsNo());
//                        obligateVO.setAmount(detail.getQty());
//                        obligateVO.setSapInArea(abnormalInVO.getSapInArea());
//                        obligateVO.setInnerOrder(abnormalInDO.getInnerOrder());
//                        obligateVO.setMoveType(abnormalInDO.getMoveType());
//                        obligateVO.setWarehouseCode(abnormalInDO.getInLocation());
//                        obligateVOList.add(obligateVO);
//                    }
//                }
//            }
//
//            //生成入库主记录和入库详情记录
//            abnormalInVO.setAbnormalNo(abnormalInDO.getAbnormalNo());
//            abnormalInAddVO.setHeaderInfo(abnormalInVO);
//            success = warehouseInboundService.saveByAbnormalIn(abnormalInAddVO, userId, orgId, null);
//            if (!success) {
//                throw new Exception("生成入库主记录和入库详情记录出错");
//            }
//
//        }
//        if (success) {
//            return new ActionResult(ErrorCode.Success.getCode(), ErrorCode.Success.getDesc(), abnormalInDO.getAbnormalNo());
//        } else {
//            return new ActionResult(ErrorCode.Failure.getCode(), ErrorCode.Failure.getDesc(), "操作失败");
//        }
//    }

    /**
     * @Author: WangKe
     * @Description: 更新记录
     * @Date: 2018/1/30 0030
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(AbnormalInAddVO abnormalInAddVO, String orgId) throws Exception {
        AbnormalInVO abnormalInVO = abnormalInAddVO.getHeaderInfo();
        List<AbnormalInDetailVO> detailList = abnormalInAddVO.getDetailList();
        //判断拆件单号是否存在
        if (!StringUtil.isNullOrEmpty(abnormalInVO.getSplitOrder())) {
            SplitDO splitDO = splitMapper.selectBySplitOrder(abnormalInVO.getSplitOrder(), orgId);
            if (splitDO == null) {
                return ErrorCode.splitNotExist;
            }
        }
        AbnormalInDetailDO detailDO = new AbnormalInDetailDO();
        boolean allComplete = true;
        boolean someComplete = false;
        boolean manulComplete = false;
        boolean success;
        for (AbnormalInDetailVO vo : detailList) {
            if (vo.getQty().compareTo(vo.getRealQty()) < 0) {  //入库数量必须大于等于实际入库数量
                return ErrorCode.InboundNumError;
            }
        }
        for (AbnormalInDetailVO vo : detailList) {

            AbnormalInDetailDO inDetailDO = abnormalInDetailMapper.selectByPrimaryKey(vo.getId());

            if (inDetailDO.getState() == 3) {
                manulComplete = true;
            }
            if (inDetailDO.getState() == 2 || inDetailDO.getState() == 3) {
                someComplete = true;
                continue;
            }

            if (vo.getQty().compareTo(vo.getRealQty()) > 0) {
                if (allComplete) {
                    allComplete = false;
                }
                if (vo.getRealQty().compareTo(BigDecimal.ZERO) == 0) {
                    detailDO.setState(0);
                } else {
                    detailDO.setState(1);
                    someComplete = true;
                }
            } else {
                someComplete = true;
                detailDO.setState(2);
            }

            //更新入库事物单详情记录
            ErrorCode errorCode = warehouseInboundService.updateDetailState(vo.getAbnormalNo(), vo.getMaterialsNo(),
                    vo.getQty(), detailDO.getState(), orgId);
            if (errorCode.getCode() != 0) {
                throw new Exception("更新入库事物单详情记录失败，" + errorCode.getDesc());
            }

            detailDO.setId(vo.getId());
            detailDO.setQty(vo.getQty());
            detailDO.setRealQty(vo.getRealQty());
            detailDO.setPrice(vo.getPrice());
            detailDO.setTotalPrice(vo.getTotalPrice());
            success = abnormalInDetailMapper.updateByPrimaryKeySelective(detailDO) > 0;
            if (!success) {
                throw new Exception("更新详情记录失败");
            }
        }
        AbnormalInDO abnormalInDO = new AbnormalInDO();
        abnormalInDO.setId(abnormalInVO.getId());
        if (allComplete) {
            if (manulComplete) {
                abnormalInDO.setState(3);
            } else {
                abnormalInDO.setState(2);
            }
        } else if (someComplete) {
            abnormalInDO.setState(1);
        } else {
            abnormalInDO.setState(0);
        }
        abnormalInDO.setSplitOrder(abnormalInVO.getSplitOrder());
        //更新操作时重置单据得审核状态
        resetAuditInfo(abnormalInDO);
        success = abnormalInMapper.update4Edit(abnormalInDO) > 0;
        if (!success) {
            throw new Exception("更新主表失败");
        }

        //更新入库事务单
        ErrorCode errorCode = warehouseInboundService.updateState(abnormalInVO.getAbnormalNo(), abnormalInDO.getState(), orgId);
        if (errorCode.getCode() != 0) {
            throw new Exception("更新入库事务单记录失败");
        }
        return errorCode;
    }

    private void resetAuditInfo(AbnormalInDO abnormalInDO) throws Exception {
        if (abnormalInDO == null) {
            throw new Exception("未查询到入库单记录");
        }
        String id = abnormalInDO.getId();
        AbnormalInDO oldAbnormalIn = abnormalInMapper.selectByPrimaryKey(id);
        if (oldAbnormalIn == null) {
            throw new Exception("未查询到入库单记录");
        }
        Integer oldAuditStatus = oldAbnormalIn.getAuditStatus();
        //如果该公司需要审核单据，并且老的审核状态是审核拒绝的，则需要把单据审核状态重置，否则直接用老单据的状态
        boolean deliveryReceiptAuditSetting = systemParameterService.getDeliveryReceiptAuditSetting(abnormalInDO.getOrgId());
        if (deliveryReceiptAuditSetting
                && oldAuditStatus != null
                && oldAuditStatus.compareTo(AbnormalInAuditStatusEnum.AUDIT_REJECT.getAuditStatus()) == 0) {
            abnormalInDO.setAuditUserName(null);
            abnormalInDO.setAuditUserId(null);
            abnormalInDO.setAuditDate(null);
            abnormalInDO.setAuditRemark(null);
            abnormalInDO.setAuditStatus(AbnormalInAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
        } else {
            abnormalInDO.setAuditUserName(oldAbnormalIn.getAuditUserName());
            abnormalInDO.setAuditUserId(oldAbnormalIn.getAuditUserId());
            abnormalInDO.setAuditDate(oldAbnormalIn.getAuditDate());
            abnormalInDO.setAuditRemark(oldAbnormalIn.getAuditRemark());
            abnormalInDO.setAuditStatus(oldAbnormalIn.getAuditStatus());
        }
    }

    public boolean update(AbnormalInDO abnormalInDO) {
        return abnormalInMapper.updateByPrimaryKey(abnormalInDO) > 0;
    }

    /**
     * @Author: WangKe
     * @Description: 根据主键删除非正常入库记录
     * @Date: 2018/1/25 0025
     */
    public ErrorCode delete(List<String> ids, String orgId) {
        List<AbnormalInDO> list = abnormalInMapper.findForDeleteByIds(ids);
        if (!ListUtil.isNullOrEmpty(list)) {
            return ErrorCode.AbnormalInDeleteError;
        }
        List<String> orderList = abnormalInMapper.findOrderList(ids);
        boolean success = abnormalInMapper.remove(ids) > 0;
        //删除入库详情记录
        if (success && CollectionUtils.isNotEmpty(orderList)) {
            abnormalInDetailService.deleteByAbnormalNoList(orderList, orgId);

            //删除事物单
            warehouseInboundService.removeByBusinessOrders(orderList, orgId);
        }
        return success ? ErrorCode.Success : ErrorCode.WarehouseIdError;
    }

    /**
     * @Author: WangKe
     * @Description: 查询非正常入库记录
     * @Date: 2018/1/25 0025
     */
    public PageCommonVO list(SearchCommonVO<AbnormalInVO> condition) {
        PageCommonVO<AbnormalInVO> pageCommonVO = new PageCommonVO();
        PageHelperPlus.orderBy("application_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<AbnormalInDO> doList = abnormalInMapper.list(condition.getFilters());
        List<AbnormalInVO> voList = new ArrayList<AbnormalInVO>();
        for (AbnormalInDO entity : doList) {
            AbnormalInVO model = new AbnormalInVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    public List<AbnormalInDO> list(AbnormalInVO vo) {
        return abnormalInMapper.list(vo);
    }

    /**
     * @Author: WangKe
     * @Description: 根据主键查找实体
     * @Date: 2018/1/19 0019
     */
    public AbnormalInAddVO findByPK(String id, String type, String orgId) {
        AbnormalInAddVO model = new AbnormalInAddVO();
        AbnormalInDO entity;
        if ("id".equals(type)) {
            entity = abnormalInMapper.selectByPrimaryKey(id);
        } else {
            entity = abnormalInMapper.selectByAbnormalNo(id, orgId);
        }
        if (entity == null) {
            return null;
        }

        //setPackageSpecName(entity);

        List<AbnormalInDetailDO> doList = abnormalInDetailService.findByAbnormalNo(entity.getAbnormalNo(), orgId);

        List<BarcodeManageDO> barCodeList = barcodeManageMapper.selectByBusinessOrderMatOrgId(entity.getAbnormalNo(), null, orgId);

        List<AbnormalInDetailVO> voList = new ArrayList<AbnormalInDetailVO>();
        if (CollectionUtils.isNotEmpty(doList)) {
            AbnormalInDetailVO abnormalInDetailVO;
            for (AbnormalInDetailDO m : doList) {
                abnormalInDetailVO = new AbnormalInDetailVO();
                BeanUtils.copyProperties(m, abnormalInDetailVO);
                abnormalInDetailVO.setLocationCode(abnormalInDetailVO.getStockLocation());
                if (StringUtils.isNotBlank(abnormalInDetailVO.getStockLocation())) {
                    abnormalInDetailVO.setLocationDesc(warehouseAreaLocationDOMapper.getLocationDesc(abnormalInDetailVO.getStockLocation()));
                }
                // 如果是条码库则设置条码相关信息
                if (!ObjectUtils.isEmpty(barCodeList)) {
                    // 设置条码字段（如果有拆分条码的情况，多个条码用逗号隔开，在入库时会拆开逐个入库）
                    String barCodes = barCodeList.stream().filter(e -> Objects.equals(e.getMaterialsNo(), m.getMaterialsNo())).map(BarcodeManageDO::getBarcode).collect(Collectors.joining(","));
                    abnormalInDetailVO.setBarCode(barCodes);
                }
                voList.add(abnormalInDetailVO);
            }
        }
        AbnormalInVO abnormalInVO = new AbnormalInVO();
        BeanUtils.copyProperties(entity, abnormalInVO);
        if (StringUtils.isNotBlank(abnormalInVO.getInLocation())) {
            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(orgId, abnormalInVO.getInLocation());
            if (null != warehouse) {
                abnormalInVO.setWarehouseCodeDesc(warehouse.getDescription());
            }
        }
        model.setHeaderInfo(abnormalInVO);
        model.setDetailList(voList);
        return model;
    }

    /**
     * @Author: WangKe
     * @Description: 导出非正常入库记录列表
     * @Date: 2018/2/7 0007
     */
    public void export(List<String> ids) throws Exception {
        invokeExport(abnormalInMapper.findByIds(ids));
    }

    /**
     * @Author: WangKe
     * @Description: 导出非正常入库记录列表
     * @Date: 2018/2/7 0007
     */
    public void exportAll(AbnormalInVO condition) throws Exception {
        Integer count = abnormalInMapper.findCountForExportAll(condition);
        List<AbnormalInDO> dataList = new ArrayList<>();
        int times = count / 500 + 1;
        for (int i = 0; i < times; i++) {
            PageHelperPlus.startPage(i + 1, 500, "APPLICATION_DATE DESC");
            dataList.addAll(abnormalInMapper.list(condition));
        }
        invokeExport(dataList);
    }

    /**
     * @Author: WangKe
     * @Description: 导出非正常入库记录列表
     * @Date: 2018/2/7 0007
     */
    private void invokeExport(List<AbnormalInDO> doList) throws Exception {
        String title = "其它入库数据导出";
        String[] rowsName = new String[]{"序号", "申请单号", "sap预留单号", "入库类型", "领入仓库",
                "制单人", "制单人部门", "制单时间", "入库状态", "SAP同步状态", "原因",
                "零件编码", "零件名称", "零件类型", "单位", "数量", "入库数量", "入库状态", "单价", "总价", "入库金额", "储位", "保管员"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            AbnormalInDO exportDO = doList.get(i);
            List<AbnormalInDetailDO> detailDOList = abnormalInDetailMapper.findByAbnormalNoForLocationUser(exportDO.getAbnormalNo(), exportDO.getOrgId());
            for (AbnormalInDetailDO detailDO : detailDOList) {
                objs = new Object[rowsName.length];
                objs[0] = i + 1;
                objs[1] = exportDO.getAbnormalNo();
                objs[2] = exportDO.getSapOrder();
                objs[3] = exportDO.getType();
                objs[4] = exportDO.getInLocation();
                objs[5] = exportDO.getCreateName();
                objs[6] = exportDO.getDept();
                objs[7] = DateUtil.formatDateTime(exportDO.getApplicationDate());
                objs[8] = getState(exportDO.getState());
                objs[9] = getSapSynState(exportDO.getIsSynsapSuccess());
                objs[10] = exportDO.getNote();
                objs[11] = detailDO.getMaterialsNo();
                objs[12] = detailDO.getMaterialsDes();
                objs[13] = detailDO.getMaterialsType();
                objs[14] = detailDO.getUnit();
                objs[15] = detailDO.getQty();
                objs[16] = detailDO.getRealQty();
                objs[17] = getState(detailDO.getState());
                objs[18] = detailDO.getPrice();
                objs[19] = detailDO.getTotalPrice();
                objs[20] = DecimalUtil.mutiply(detailDO.getPrice(), detailDO.getRealQty());
                objs[21] = detailDO.getStockLocation();
                objs[22] = detailDO.getStockUserName();
                dataList.add(objs);
            }
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getState(Integer state) {
        if (state == null) {
            state = 0;
        }
        if (state == 0) {
            return "未入库";
        } else if (state == 1) {
            return "部分入库";
        } else if (state == 2) {
            return "已入库";
        } else {
            return "强制结单";
        }
    }
//
//    private static BigDecimal takeDecimals(BigDecimal integer) {
//        if (integer == null) {
//            return new BigDecimal(0);
//        }
//        return integer.divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
//    }
//
//    private static BigDecimal rounding(BigDecimal decimal) {
//        if (decimal == null) {
//            return new BigDecimal(0);
//        }
//        return decimal.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP);
//    }

    private String getSapSynState(Integer state) {
        if (state == null) {
            state = 0;
        }
        if (state == 0) {
            return "未同步";
        } else if (state == 1) {
            return "同步成功";
        } else {
            return "同步失败";
        }
    }

    /**
     * @Author: WangKe
     * @Description: 零件批量导入
     * @Date: 2018/3/1 0001
     */
    public FunctionResult importExcel(InputStream in, String orgId, String supplierOrgId) throws Exception {
        FunctionResult result = new FunctionResult();
        HSSFWorkbook wb = new HSSFWorkbook(in);
        HSSFSheet sheet = wb.getSheetAt(0);

        int totalRow = sheet.getLastRowNum();
        if (totalRow < 2) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell = sheet.getRow(1).getLastCellNum();
        if (totalCell != 4) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<AbnormalInDetailVO> detailVOList = new ArrayList<>();
        List<AbnormalInDetailVO> successVOList = new ArrayList<>(totalRow);

        Set<String> materials = new HashSet<>(totalRow);
        for (int i = 2; i <= totalRow; i++) {
            HSSFRow curRow = sheet.getRow(i);
            AbnormalInDetailVO detailVO = new AbnormalInDetailVO();
            if (curRow == null) {
                continue;
            }
            detailVO.setRownum(i + 1);
            String materialNo = xcmg.device.util.ExcelUtil.getCellValue(curRow, 1);
            if (StringUtil.isNullOrEmpty(materialNo)) {
                detailVO.setRemark("零件编码不能为空");
                throw new CommonBusiExceptions(detailVO.getRownum() + "行:零件编码不能为空");
            }
            if (materials.contains(materialNo)) {
                detailVO.setRemark("零件编码重复出现");
                throw new CommonBusiExceptions(detailVO.getRownum() + "行:零件编码重复出现");
            }
            detailVO.setMaterialsNo(materialNo);
            materials.add(materialNo);
            String qtyStr = xcmg.device.util.ExcelUtil.getCellValue(curRow, 3);
            detailVO.setQty(DecimalUtil.getStringDecimal(qtyStr));
            detailVOList.add(detailVO);
        }
        MaterialsSearchVO mv = new MaterialsSearchVO();
        mv.setSupplierOrgId(supplierOrgId);
        mv.setOrgId(orgId);
        mv.setMaterialsList(new ArrayList<>(materials));
        List<MaterialsVO> resultList = priMaterialsMapper.querySupplierMaterials(mv);
        Map<String, MaterialsVO> map = resultList.stream().collect(Collectors.toMap(MaterialsVO::getMaterialsNo, v -> v));

        for (AbnormalInDetailVO v : detailVOList) {
            MaterialsVO m = map.get(v.getMaterialsNo());
            if (null == m) {
                v.setRemark("零件编码在供货商下不存在");
                throw new CommonBusiExceptions(v.getRownum() + "行:零件编码在供货商下不存在");
            }
            v.setMaterialsDes(m.getMaterialsDes());
            v.setMaterialsDesEn(m.getMaterialsDesEn());
            v.setUnit(m.getUnit());
            v.setMaterialsShortNo(m.getMaterialsShortNo());
            v.setModelCode(m.getModelCode());
            successVOList.add(v);
        }

        result.setValue(successVOList);
        result.setCode(ErrorCode.Success);
        return result;
    }

//    private boolean isInteger(String str) {
//        if (null == str || "".equals(str)) {
//            return false;
//        }
//        try {
//            BigDecimal decimal = new BigDecimal(str);
//        } catch (Exception e) {
//            return false;
//        }
//        return true;
//    }

    private String getCellValue(HSSFRow curRow, int i) {
        String value = "";
        if (curRow.getCell(i) != null) {
            curRow.getCell(i).setCellType(CellType.STRING);
            value = curRow.getCell(i).getStringCellValue();
        }
        return value;
    }

    public void download() throws Exception {
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }

    /**
     * 手动完成单据<br>
     * materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态
     *
     * @param billNo      String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId       String 企业ID
     * @return ErrorCode 返回码
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manualFinish(String billNo, String materialsNo, String orgId) throws Exception {
        AbnormalInDO abnormalInDO = abnormalInMapper.selectByAbnormalNo(billNo, orgId);

        if (StringUtil.isNullOrEmpty(materialsNo))//零件编码为空，更新单据状态为“手动完成”
        {
            abnormalInDO.setState(OUT_STATUS_FINISH);
            abnormalInDO.setPostStatus(POST_STATUS_YES);
            abnormalInMapper.updateByPrimaryKeySelective(abnormalInDO);

            warehouseInboundService.updateState(billNo, 3, orgId);
            abnormalInDetailMapper.updateStateNoBarcode(3, billNo, null, orgId);
            warehouseInboundDetailMapper.updateAllStatus(3, billNo, orgId);
        } else {
            abnormalInDetailMapper.updateStateNoBarcode(3, billNo, materialsNo, orgId);
            warehouseInboundService.updateDetailState(billNo, materialsNo, null, 3, orgId);

            return checkBillFinished(billNo, orgId);
        }
        return ErrorCode.Success;
    }

    /**
     * 校验单据是否已完成<br>
     * 判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     *
     * @param billNo String
     * @param orgId  String
     * @return Boolean
     */
    private ErrorCode checkBillFinished(String billNo, String orgId) throws Exception {
        List<AbnormalInDetailDO> inDetailDOs = abnormalInDetailMapper.findByAbnormalNo(billNo, orgId);
        if (ListUtil.isNullOrEmpty(inDetailDOs)) {
            throw new Exception("未查询到非正常入库单详情列表");
        }
        boolean manul = false;
        boolean flag = true;
        int status;
        for (AbnormalInDetailDO temp : inDetailDOs) {
            if (temp.getState() == 3) {
                manul = true;
            }
            if (2 == temp.getState() || 3 == temp.getState()) {
                //完成状态
                continue;
            }
            flag = false;
        }
        if (flag) {
            if (manul) {
                status = 3;
            } else {
                status = 2;
            }
        } else {
            status = 1;
        }
        abnormalInMapper.updateStateNoBarcode(status, billNo, orgId);
        warehouseInboundService.updateState(billNo, status, orgId);
        return ErrorCode.Success;
    }

    public Integer countAuditData(String orgId) {
        Integer count = abnormalInMapper.countAuditData(orgId);
        return count == null ? 0 : count;
    }
}
